# MT::Plugin::MobileText
# Author: Takashi Ishikawa (http://www.ana-kutsu.com/)
# Copyright (C) 2011, Takashi Ishikawa.
#
# This program is distributed under the terms of the
# GNU General Public License, version 2.


package MT::Plugin::MobileText;

use strict;
use MT;
use MT::Plugin;
use MT::I18N;
use charnames ':full';
use Unicode::Normalize;

our $VERSION = '1.0';

use base qw(MT::Plugin);

@MT::Plugin::MobileText::ISA = qw(MT::Plugin);

my $objPlugin = new MT::Plugin::MobileText({
	id => 'MobileText',
	key => 'mobile_text',
	description => '<MT_TRANS phrase=\'_PLUGIN_DESCRIPTION\'>',
	name => 'MobileText',
	author_name => 'Takashi Ishikawa',
	author_link => 'http://www.ana-kutsu.com/',
	version => $VERSION,
	l10n_class => 'MobileText::L10N',
});

MT->add_plugin($objPlugin);

MT::Template::Context->add_container_tag('MobileText' => \&mobile_text);

# CORE Module only zen>han conversation
# http://blog.livedoor.jp/dankogai/archives/51220946.html
sub _getHankakuZenkakuKatakana {
	my $strHankaku = '';
	my $strZenkaku = '';
	my $numCode = 0;
	my $strName = '';
	
	for ($numCode = 0xFF61; $numCode <= 0xFF9D; $numCode++) {
		$strHankaku .= chr($numCode);
		$strName = charnames::viacode($numCode);
		$strName =~ s/HALFWIDTH\s+//;
		$strZenkaku .= chr(charnames::vianame($strName));
	}
	
	return ($strHankaku, $strZenkaku);
}

sub _getHiraganaNFC {
	my ($strContent) = @_;
	my @listFrom = (
		"\x{304B}\x{FF9E}",
		"\x{304D}\x{FF9E}",
		"\x{304F}\x{FF9E}",
		"\x{3051}\x{FF9E}",
		"\x{3053}\x{FF9E}",
		"\x{3055}\x{FF9E}",
		"\x{3057}\x{FF9E}",
		"\x{3059}\x{FF9E}",
		"\x{305B}\x{FF9E}",
		"\x{305D}\x{FF9E}",
		"\x{305F}\x{FF9E}",
		"\x{3061}\x{FF9E}",
		"\x{3064}\x{FF9E}",
		"\x{3066}\x{FF9E}",
		"\x{3068}\x{FF9E}",
		"\x{306F}\x{FF9E}",
		"\x{3072}\x{FF9E}",
		"\x{3075}\x{FF9E}",
		"\x{3078}\x{FF9E}",
		"\x{307B}\x{FF9E}",
		"\x{306F}\x{FF9F}",
		"\x{3072}\x{FF9F}",
		"\x{3075}\x{FF9F}",
		"\x{3078}\x{FF9F}",
		"\x{307B}\x{FF9F}"
	);
	my @listTo = (
		"\x{304C}",
		"\x{304E}",
		"\x{3050}",
		"\x{3052}",
		"\x{3054}",
		"\x{3056}",
		"\x{3058}",
		"\x{305A}",
		"\x{305C}",
		"\x{305E}",
		"\x{3060}",
		"\x{3062}",
		"\x{3065}",
		"\x{3067}",
		"\x{3069}",
		"\x{3070}",
		"\x{3073}",
		"\x{3076}",
		"\x{3079}",
		"\x{307C}",
		"\x{3071}",
		"\x{3074}",
		"\x{3077}",
		"\x{307A}",
		"\x{307D}"
	);
	
	for (my $numIndex = 0; $numIndex <= $#listFrom; $numIndex++) {
		$strContent =~ s/$listFrom[$numIndex]/$listTo[$numIndex]/eg;
	}
	
	return $strContent;
}

sub _convertZenkakuHankaku {
	my ($strContent) = @_;
	my ($strHankakuKatakana, $strZenkakuKatakana) = _getHankakuZenkakuKatakana();
	my $strHankaku = 
		"\x{0021}" .    "\x{0023}\x{0024}\x{0025}" .            "\x{0028}\x{0029}\x{002A}\x{002B}\x{002C}\x{002D}\x{002E}" .    "\x{0030}" .
		"\x{0031}\x{0032}\x{0033}\x{0034}\x{0035}\x{0036}\x{0037}\x{0038}\x{0039}\x{003A}\x{003B}" .    "\x{003D}" .    "\x{003F}\x{0040}" .
		"\x{0041}\x{0042}\x{0043}\x{0044}\x{0045}\x{0046}\x{0047}\x{0048}\x{0049}\x{004A}\x{004B}\x{004C}\x{004D}\x{004E}\x{004F}\x{0050}" .
		"\x{0051}\x{0052}\x{0053}\x{0054}\x{0055}\x{0056}\x{0057}\x{0058}\x{0059}\x{005A}\x{005B}" .    "\x{005D}\x{005E}\x{005F}\x{0060}" .
		"\x{FF9E}\x{FF9F}";
	my $strZenkaku = 
		"\x{FF01}" .    "\x{FF03}\x{FF04}\x{FF05}" .            "\x{FF08}\x{FF09}\x{FF0A}\x{FF0B}\x{FF0C}\x{FF0D}\x{FF0E}" .    "\x{FF10}" .
		"\x{FF11}\x{FF12}\x{FF13}\x{FF14}\x{FF15}\x{FF16}\x{FF17}\x{FF18}\x{FF19}\x{FF1A}\x{FF1B}" .    "\x{FF1D}" .    "\x{FF1F}\x{FF20}" .
		"\x{FF21}\x{FF22}\x{FF23}\x{FF24}\x{FF25}\x{FF26}\x{FF27}\x{FF28}\x{FF29}\x{FF2A}\x{FF2B}\x{FF2C}\x{FF2D}\x{FF2E}\x{FF2F}\x{FF30}" .
		"\x{FF31}\x{FF32}\x{FF33}\x{FF34}\x{FF35}\x{FF36}\x{FF37}\x{FF38}\x{FF39}\x{FF3A}\x{FF3B}" .    "\x{FF3D}\x{FF3E}\x{FF3F}\x{FF40}" .
		"\x{3099}\x{309A}";
	
	*_TrKatakana = eval("sub { local \$_ = shift; tr/$strZenkakuKatakana/$strHankakuKatakana/; \$_ }");
	*_TrAlphanum = eval("sub { local \$_ = shift; tr/$strZenkaku/$strHankaku/; \$_ }");
	
	return _getHiraganaNFC(NFC(_TrAlphanum(_TrKatakana(NFD($strContent)))));
}

sub mobile_text {
	my ($objContxt, $listParam) = @_;
	my $objBuilder = $objContxt->stash('builder');
	my $objToken = $objContxt->stash('tokens');
	my $strEncodeFrom = '';
	my $strEncodeTo = '';
	my $flagHankaku = '';
	my $flagSmart = '';
	my $strContent = '';
	my $strEncoding = '';
	my $result = '';
	
	# initialize variable
	if (defined($listParam->{'encode_from'})) {
		$strEncodeFrom = $listParam->{'encode_from'};
	}
	if (defined($listParam->{'encode_to'})) {
		$strEncodeTo = $listParam->{'encode_to'};
	}
	if (defined($listParam->{'hankaku'})) {
		$flagHankaku = $listParam->{'hankaku'};
	}
	if (defined($listParam->{'smart'})) {
		$flagSmart = $listParam->{'smart'};
	}
	# call super
	$strContent = $objBuilder->build($objContxt, $objToken);
	if (defined($strContent)) {
		# convert internal encoding
		if (!$strEncodeFrom) {
			$strEncodeFrom = MT::I18N::guess_encoding($strContent);
		}
		if ($strEncodeFrom ne 'utf8') {
			$strContent = MT::I18N::encode_text($strContent, $strEncodeFrom, 'utf8');
		}
		# convert to hankaku
		if ($flagHankaku) {
			$strContent = _convertZenkakuHankaku($strContent);
		}
		# delete return, space and tab
		if ($flagSmart) {
			$strContent =~ s/>\s*</></g;
		}
		# convert encoding
		if (!$strEncodeTo) {
			$strEncodeTo = $strEncodeFrom;
		}
		if ($strEncodeTo ne 'utf8') {
			$strContent = MT::I18N::encode_text($strContent, 'utf8', $strEncodeTo);
		}
		$result = $strContent;
	} else {
		$result = $objContxt->error($objBuilder->errstr);
	}
	
	return $result;
}

1;